/*
 * ChangeLog
 * Date             Author          Note
 * 2014.07.14       Herbert         First version
 * 2014.08.28       Herbert         BACKPIECE结构体增加prange成员，删除pattern_start和pattern_end
 *                                  获取从第一行到最后一行每一行的编织宽度
 * 2014.09.02       Herbert         backpiece_iterate函数遍历每行每颗针是否有线圈，来记录每行的范围
 * 2014.09.19       Herbert         增加前片结束行的记录
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <mh/common.h>
#include <mh/sram.h>
#include <mh/mac.h>
#include "knit.h"
#include "translator.h"
#include "backpiece.h"

/*
 * 获取线圈的起始位置和结束位置
 */
void backpiece_get_range(int *fstitch, int *bstitch, int *ps, int *pe, int width)
{
    assert(fstitch != NULL);
    assert(bstitch != NULL);
    assert(ps != NULL);
    assert(pe != NULL);

    int i = 0;
    /* 起点 */
    for (i = 0; i < width; i++)
    {
        if ((fstitch[i] != 0) || (bstitch[i] != 0))
        {
            *ps = i;
            break;
        }
    }

    /* 终点 */
    for (i = width; i >= 0; i--)
    {
        if ((fstitch[i] != 0) || (bstitch[i] != 0))
        {
            *pe = i;
            break;
        }
    }
}
/*
 *
 */
void backpiece_iterate(MH_KNIT *p)
{
#define START_BIT   (0x01 << 2)
#define END_BIT     (0x01 << 3)
    int i = 0;
    TRANSLATOR translator;
    int ps = 0;      /* pattern start */
    int pe = 0;      /* pattern end */
    int end_line = p->total_line;
    int *fstitch;
    int *bstitch;
    p->backpiece.start_row = -1;
    p->backpiece.end_row = -1;
    p->backpiece.fp_end_row = -1;
    FREE (p->backpiece.prange);

    p->backpiece.prange = calloc(end_line + 1, sizeof (PAT_RANGE));


    translator.width = p->flower_width;
    translator.height = p->flower_height;
    translator.pat_buf = p->flower_data;

    fstitch = calloc(translator.width, sizeof (int));
    bstitch = calloc(translator.width, sizeof (int));

    for (i = 1; i <= end_line; i++)
    {
        KNIT_PAGE *con = GetControlPage(p, i);
        if (con->end.end & START_BIT)
        {
            if (p->backpiece.start_row < 0)
            {
                p->backpiece.start_row = i;
            }
        }
        if (con->end.end & END_BIT)
        {
            /* 如果先找到了结束行，该行为前片的结束行 */
            if (p->backpiece.start_row < 0)
            {
                p->backpiece.fp_end_row = i;
            }
            else if (p->backpiece.end_row < 0)
            {
                p->backpiece.end_row = i;
            }
        }

        translator_set_stitch(&translator, fstitch, bstitch, (uchar*)con);

        backpiece_get_range(fstitch, bstitch, &ps, &pe, translator.width);
        p->backpiece.prange[i].pat_start = ps;
        p->backpiece.prange[i].pat_end = pe;
    }

    FREE(fstitch);
    FREE(bstitch);
}
/*
 *
 */
int backpiece_valid(MH_KNIT *p)
{
    PAT_RANGE range;
    if (p->board_enable)
    {
        return FALSE;
    }

    if (p->backpiece.prange == NULL)
    {
        return FALSE;
    }

    backpiece_get_first_row_range(p, &range);

    if (p->backpiece.start_row > 0 &&
        p->backpiece.end_row > 0 &&
        range.pat_start >= 0 &&
        range.pat_end >= 0)
    {
        if (p->backpiece.end_row > p->backpiece.start_row)
        {
            return TRUE;
        }
    }

    return FALSE;
}
/*
 *
 */
int backpiece_get_start_row(MH_KNIT *p)
{
    return p->backpiece.start_row;
}
/*
 *
 */
int backpiece_get_end_row(MH_KNIT *p)
{
    return p->backpiece.end_row;
}
/*
 *
 */
int backpiece_get_fp_end_row(MH_KNIT *p)
{
    return p->backpiece.fp_end_row;
}
/*
 * 获取后片第一行的色码范围，目的是为了后片循环时，后片机头纱的宽度和后片第一行的宽度保持一致
 */
void backpiece_get_first_row_range(MH_KNIT *p, PAT_RANGE *range)
{
    assert (range != NULL);
    int sr = p->backpiece.start_row;
    if (sr >= 1 && sr <= p->total_line)
    {
        range->pat_start = p->backpiece.prange[sr].pat_start;
        range->pat_end = p->backpiece.prange[sr].pat_end;
    }
}
/*
 *
 */
void backpiece_get_pattern_range(MH_KNIT *p, int row, PAT_RANGE *range)
{
    assert (range != NULL);
    if (row >= 1 && row <= p->total_line && p->backpiece.prange)
    {
        range->pat_start = p->backpiece.prange[row].pat_start;
        range->pat_end = p->backpiece.prange[row].pat_end;

        if (row > p->backpiece.end_row)
        {
            if (p->knit_state.bp_enable)
            {
                int sr = p->backpiece.start_row;
                /* 后片使能时，并且不是最后一片,后片废纱以上的宽度与后片起始行宽度相同　*/
                if (p->done_cloth + 1 < p->total_cloth)
                {
                    range->pat_start = p->backpiece.prange[sr].pat_start;
                    range->pat_end = p->backpiece.prange[sr].pat_end;
                }
            }
        }
    }
}
/*
 *
 */
void backpiece_free(MH_KNIT *p)
{
    FREE (p->backpiece.prange);
}
/*
 * 判断第row行是否废纱，从１开始
 */
int backpiece_is_refuseyarn(MH_KNIT *p, int row)
{
    if ((p->backpiece.fp_end_row > 0) &&
        (p->backpiece.start_row > 0) &&
        (p->backpiece.end_row > 0))
    {
        if ((row > p->backpiece.fp_end_row && row < p->backpiece.start_row) ||
            (row > p->backpiece.end_row))
        {
            return TRUE;
        }
    }
    else if (p->backpiece.fp_end_row > 0)
    {
        if (row > p->backpiece.fp_end_row)
        {
            return TRUE;
        }
    }
    else if (p->backpiece.end_row > 0)
    {
        if (row > p->backpiece.end_row)
        {
            return TRUE;
        }
    }

    return FALSE;
}
/*
 *
 */
void backpiece_set_refuseyarn_flag(MH_KNIT *p, int row)
{
    if ((p->backpiece.fp_end_row > 0) &&
        (p->backpiece.start_row > 0) &&
        (p->backpiece.end_row > 0))
    {
        if ((row > p->backpiece.fp_end_row) && (row < p->backpiece.start_row))
        {
            p->need_loop |= LOOP_FRY_BIT;
        }
        else
        {
            p->need_loop &= ~LOOP_FRY_BIT;
        }

        if (row > p->backpiece.end_row)
        {
            p->need_loop |= LOOP_BRY_BIT;
        }
        else
        {
            p->need_loop &= ~LOOP_BRY_BIT;
        }
    }
    else if (p->backpiece.fp_end_row > 0)
    {
        if (row > p->backpiece.fp_end_row)
        {
            p->need_loop |= LOOP_FRY_BIT;
        }
        else
        {
            p->need_loop &= ~LOOP_FRY_BIT;
        }
    }
    else if (p->backpiece.end_row > 0)
    {
        if (row > p->backpiece.end_row)
        {
            p->need_loop |= LOOP_BRY_BIT;
        }
        else
        {
            p->need_loop &= ~LOOP_BRY_BIT;
        }
    }

}
/*
 *
 */
void backpiece_save_refuseyarn_range(MH_KNIT *p)
{
    /* 前片结束行范围 */
    PAT_RANGE fp_er = { 0 };
    /* 后片结束行范围 */
    PAT_RANGE bp_er = { 0 };
    /* 前片结束行 */
    int fp_end_row = backpiece_get_fp_end_row(p);
    /* 后片结束行 */
    int bp_end_row = backpiece_get_end_row(p);

    backpiece_get_pattern_range(p, fp_end_row, &fp_er);
    backpiece_get_pattern_range(p, bp_end_row, &bp_er);

    p->fper_pat_start = fp_er.pat_start;
    p->fper_pat_end = fp_er.pat_end;

    p->bper_pat_start = bp_er.pat_start;
    p->bper_pat_end = bp_er.pat_end;
}
/*
 *
 */
int GetFrontPieceEnable(MH_KNIT *p)
{
    return p->knit_state.fp_enable;
}
/*
 *
 */
void SetFrontPieceEnable(MH_KNIT *p, int enable)
{
    p->knit_state.fp_enable = enable;
}
/*
 *
 */
int GetBackPieceEnable(MH_KNIT *p)
{
    return p->knit_state.bp_enable;
}
/*
 *
 */
void SetBackPieceEnable(MH_KNIT *p, int enable)
{
    p->knit_state.bp_enable = enable;
}
/*
 *
 */
uint GetSourceTotalCloth(MH_KNIT *p)
{
    return p->total_cloth_backup;
}
/*
 *
 */
uint GetSourceDoneCloth(MH_KNIT *p)
{
    return p->done_cloth_backup;
}
/*
 *
 */
ushort SwitchKnitPiece(MH_KNIT *p, uint total, uint finish)
{
    return p->knit_state.bp_enable ? p->backpiece_start_line : 1;
}
/*
 *
 */
int GetBackPieceValid(MH_KNIT *p)
{
    return backpiece_valid(p);
}
/*
 *
 */
void DivideBackPiece(MH_KNIT *p)
{
    backpiece_iterate(p);
}
/*
 *
 */
void InitBackPiece(MH_KNIT *p)
{
    if(GetBackPieceEnable(p) && GetBackPieceValid(p))
    {
        p->backpiece_start_line = backpiece_get_start_row(p);
    }
}
/*
 *
 */
ushort GetBackPieceStart(MH_KNIT *p)
{
    return p->backpiece_start_line;
}
/*
 *
 */
ushort GetKnitStartLine(MH_KNIT *p)
{
    ushort start_line = 1;
    if(GetBackPieceValid(p) && GetBackPieceEnable(p))
    {
        start_line = GetBackPieceStart(p);
    }
    return start_line;
}
/*
 *
 */
ushort GetKnitEndLine(MH_KNIT *p)
{
    ushort end_line = p->total_line;
    if(GetBackPieceValid(p) && GetFrontPieceEnable(p))
    {
        end_line = GetBackPieceStart(p) - 1;
    }
    return end_line;
}
/*
 *
 */
int GetCoilStart(MH_KNIT *p)
{
    return p->knit_start;
}
/*
 *
 */
void SetCoilStart(MH_KNIT *p, int n)
{
    p->knit_start = n;
}
/*
 *
 */
int GetCoilEnd(MH_KNIT *p)
{
    return p->knit_end;
}
/*
 *
 */
void SetCoilEnd(MH_KNIT *p, int n)
{
    p->knit_end = n;
}
/*
 *
 */
int GetCoilKnitStartPoint(MH_KNIT *p)
{
    return p->sp;
}
/*
 *
 */
void SetCoilKnitStartPoint(MH_KNIT *p, int n)
{
    p->sp = n;
}
/*
 *
 */
void GetAutoHdData(MH_KNIT *p)
{
    if(p->knit_state.auto_hd_drop && p->need_loop &&
        (p->hangding_enable != HD_START) && (p->hangding_enable != HD_FORBID_MODIFY))
    {
        /* 自动打行定 */
        if(p->curt_line + 1 == p->backpiece_start_line || p->curt_line == 0)
        {
            int sp = p->start_needle - p->left_bound;
            PAT_RANGE range = { 0 };
            backpiece_get_pattern_range(p, p->curt_line + 1, &range);
            int knit_start = range.pat_start;
            int knit_end = range.pat_end;
            /* 宽度不一样自动打行定 */
            if((p->knit_start + p->sp > knit_start + sp) || (p->knit_end
                    + p->sp < knit_end + sp) || ((p->need_loop & LOOP_BITS)
                    != 0))
            {
                int dl = p->knit_start + p->sp - (knit_start + sp);
                int dr = p->knit_end + p->sp - (knit_end + sp);
                int d = __max(abs(dl), abs(dr));

                p->hangding_enable = HD_START;
                p->knit_state.hd_forever = FALSE;
                p->hangding_start = p->curt_line + p->hd_start_base;
                p->hangding_end = p->curt_line + p->hd_end_base;
                p->economy_left = 0;

                if(d > 0)
                {
                    if(d <= 5)
                    {
                        p->economy_left = 3;
                    }
                    else if(d <= 10)
                    {
                        p->economy_left = 10;
                    }
                    else if(d <= 15)
                    {
                        p->economy_left = 18;
                    }
                    else
                    {
                        p->economy_left = 25;
                    }
                }

                if((p->need_loop & LOOP_SY_BIT)
                        || ((p->need_loop & LOOP_KC_BIT) == KNITING))
                {
                    p->economy_left = 25;
                }
                else if(p->need_loop & LOOP_YC_BIT)
                {
                    if(p->economy_left < 3)
                    {
                        p->economy_left = 3;
                    }
                }
                p->economy_times = p->economy_left;
            }
        }
        p->need_loop = 0;
        p->need_loop_record = 0;
    }
}
